﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////

#include <QLabel>
#include <QTimer>
#include <QHBoxLayout>
#include <QGraphicsDropShadowEffect>
#include <QGraphicsOpacityEffect>
#include <QPropertyAnimation>
#include <QPixmap>
#include <QPainter>
#include <QFontMetrics>
#include <QUuid>
#include <QEvent>

// gcmp headers

// custom headers
#include "CustomBallon.h"
#include "WidgetUtils.h"
#include "GbmpNew.h"
#include "DebugMessage.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h" 


namespace gmepgcs
{
    CustomBallon::CustomBallon(QWidget *targetWidget) :
        QWidget(WidgetUtils::GetRootWidget(targetWidget)),
        m_rootWidget(WidgetUtils::GetRootWidget(targetWidget)),
        m_targetWidget(targetWidget),
        m_pLblIcon(nullptr),
        m_pLblText(nullptr),
        m_textFont(),
        m_key(QUuid::createUuid().toString())
    {
        Init();
    }

    CustomBallon::~CustomBallon()
    {

    }

    CustomBallon * CustomBallon::Get(const QString & key)
    {
        auto foundIterator = CustomBallon::s_mpBallons.find(key);
        if (foundIterator == CustomBallon::s_mpBallons.end())
        {
            return nullptr;
        }

        return foundIterator->second;
    }

    void CustomBallon::Destroy(const QString &key)
    {
        auto foundIterator = CustomBallon::s_mpBallons.find(key);
        if (foundIterator == CustomBallon::s_mpBallons.end())
        {
            return;
        }

        auto foundBallon = foundIterator->second;
        if (foundBallon)
        {
            foundBallon->setParent(nullptr);
            delete foundBallon;
            foundBallon = nullptr;
        }

        CustomBallon::s_mpBallons.erase(key);
    }

    bool CustomBallon::eventFilter(QObject * watched, QEvent * event)
    {
        if (watched && (watched == m_targetWidget) && event && (event->type() == QEvent::Type::Move))
        {
            AdjustPosition();
        }

        if (watched && (watched == m_rootWidget) && event && (event->type() == QEvent::Type::Resize))
        {
            AdjustPosition();
        }

        return false;
    }

    void CustomBallon::paintEvent(QPaintEvent * event)
    {
        // draw background
        QPainter painter(this);
        painter.fillRect(rect(), QBrush(QColor(255, 110, 100, 255), Qt::BrushStyle::SolidPattern));

        QWidget::paintEvent(event);
    }

    void CustomBallon::Init()
    {
        // self
        setWindowFlags(Qt::WindowStaysOnTopHint);
        setAttribute(Qt::WA_DeleteOnClose, true);
        setMinimumHeight(24);
        if (m_targetWidget)
        {
            m_targetWidget->installEventFilter(this);
        }
        if (m_rootWidget)
        {
            m_rootWidget->installEventFilter(this);
        }

        // layout 
        QHBoxLayout *pLayout = NEW_AS_QT_CHILD(QHBoxLayout, this);
        DBG_WARN_AND_RETURN_VOID_UNLESS(pLayout, L"pLayout为空", L"GMEP", L"2024-01-30");
        pLayout->setContentsMargins(8, 0, 8, 0);
        pLayout->setSpacing(8);
        setLayout(pLayout);

        // icon
        m_pLblIcon = NEW_AS_QT_CHILD(QLabel,this);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pLblIcon, L"m_pLblIcon为空", L"GMEP", L"2024-01-30");
        m_pLblIcon->setFixedSize(QSize(16, 16));
        m_pLblIcon->setScaledContents(true);
        pLayout->addWidget(m_pLblIcon);
        pLayout->setAlignment(m_pLblIcon, Qt::AlignVCenter | Qt::AlignLeft);

        // text
        m_pLblText = NEW_AS_QT_CHILD(QLabel,this);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_pLblText, L"m_pLblText为空", L"GMEP", L"2024-01-30");
        m_pLblText->setSizePolicy(QSizePolicy::Policy::Expanding, QSizePolicy::Policy::Fixed);
        m_pLblText->setStyleSheet(
            QString(
                "QLabel{"
                "font-family:\"Microsoft YaHei\";"
                "font-size:12px;"
                "color:rgba(255, 255, 255, 255);"
                "}"
            )
        );
        pLayout->addWidget(m_pLblText);
        pLayout->setAlignment(m_pLblText, Qt::AlignVCenter | Qt::AlignLeft);
    }

    QString CustomBallon::Key()
    {
        return m_key;
    }

    CustomBallon * CustomBallon::ConfigIcon(const BallonIcon & icon)
    {
        QString iconPath;
        switch (icon)
        {
        case BallonIcon::Info:
            iconPath = ":/images/Announcement/Info/16x16.png";
            break;
        case BallonIcon::Warning:
            iconPath = ":/images/Announcement/HighWarning/16x16.png";
            break;
        case BallonIcon::Error:
            iconPath = ":/images/Announcement/Error/16x16.png";
            break;
        case BallonIcon::Success:
            iconPath = ":/images/Announcement/Success/16x16.png";
            break;
        case BallonIcon::Close:
            iconPath = ":/images/Announcement/CloseNoBackGround/16x16.png";
            break;
        case BallonIcon::Waiting:
            iconPath = ":/images/Announcement/Waiting/16x16.png";
            break;
        default:
            break;
        }
        DBG_WARN_AND_RETURN_UNLESS(m_pLblIcon, this, L"m_pLblIcon 为空", L"GMEP", L"2024-01-30");
        if (!iconPath.isEmpty())
        {
            QPixmap iconPixmap;
            iconPixmap.load(iconPath);
            m_pLblIcon->setPixmap(iconPixmap.scaled(m_pLblIcon->size(), Qt::KeepAspectRatio, Qt::TransformationMode::SmoothTransformation));
            m_pLblIcon->setVisible(true);
        }
        else
        {
            m_pLblIcon->clear();
            m_pLblIcon->setVisible(false);
        }
        
        adjustSize();
        AdjustPosition();
        return this;
    }

    CustomBallon * CustomBallon::ConfigMessage(const std::wstring & message)
    {
        DBG_WARN_AND_RETURN_UNLESS(m_pLblText, this, L"m_pLblText 为空", L"GMEP", L"2024-01-30");
        m_pLblText->setText(QString::fromStdWString(message));
        adjustSize();
        AdjustPosition();
        return this;
    }
    
    CustomBallon * CustomBallon::ConfigPosition(const QPoint &pos)
    {
        move(pos);
        return this;
    }

    CustomBallon * CustomBallon::ConfigSize(int width, int height)
    {
        setFixedSize(width, height);
        return this;
    }

    CustomBallon * CustomBallon::AdjustPosition()
    {
        ConfigPosition(WidgetUtils::MapToAncestor(m_targetWidget, m_rootWidget, QPoint(0, 0)) + QPoint(0, -height()));
        return this;
    }

    std::map<QString, CustomBallon*> CustomBallon::s_mpBallons = std::map <QString, CustomBallon*>();
}